import { logger } from '../../utils/web-logger.util'
import { promises as fs, existsSync } from 'fs'
import path from 'path'
import { HTTPRequest } from 'puppeteer'


export const REPORT_BASE_PATH = path.join(__dirname, '..', '..', '..');

const FONT_CACHE: {
  [key: string]: Buffer;
} = {};

export const RequestHandler: (req: HTTPRequest, ...args: any[]) => void = async (req, args) => {
  const url = req.url();
  if (url.startsWith('data:')) {
    await req.continue();
    return;
  }


  try {
    if (url.endsWith('ttf')) {
      const data = await readFont(url);
      await req.respond({
        status: 200,
        contentType: 'font/ttf',
        body: data,
      });
      return;
    }
    if (url.endsWith('rdlx-json')) {
      const data = await readTemplate(url);
      await req.respond({
        status: 200,
        contentType: 'application/json',
        body: data,
        headers: {
          'Cache-Control': 'max-age=2592000000,public,immutable',
        },
      });
      return;
    }
    if (url.endsWith('png') || url.endsWith('jpg') || url.endsWith('jpeg')) {
      const data = await readImage(url);
      await req.respond({
        status: 200,
        contentType: 'image/png',
        body: data,
      });
      return;
    }
  } catch (err) {
    logger.error(err);
    await req.respond({
      status: 500,
      contentType: 'text/html',
      body: `<div>no such font file: ${err.message}</div>`,
    });
  }
  logger.error(`unable to find the resource for ${url}`);
  await req.abort();
}
const readImage = async (url: string): Promise<Buffer> => {
  if (FONT_CACHE[url]) {
    return FONT_CACHE[url];
  }
  const files = await fs.readdir(REPORT_BASE_PATH + '/reports/images');
  const urlf = url.replace(/%20/g, ' ');
  const file = files.find(file => urlf.endsWith(file));
  if (!file) {
    throw new Error(`unable to find image file for ${urlf}`);
  }
  const data = await fs.readFile(`${REPORT_BASE_PATH}/reports/images/${file}`);
  FONT_CACHE[url] = data;
  return data;
}
const readFont = async (url: string): Promise<Buffer> => {
  if (FONT_CACHE[url]) {
    return FONT_CACHE[url];
  }
  const files = await fs.readdir(REPORT_BASE_PATH + '/reports/static/fonts');
  const urlf = url.replace(/%20/g, ' ');
  const file = files.find(file => urlf.endsWith(file));
  if (!file) {
    throw new Error(`unable to find font file for ${urlf}`)
  }
  const data = await fs.readFile(`${REPORT_BASE_PATH}/reports/static/fonts/${file}`);
  FONT_CACHE[url] = data;
  return data;
}
const readTemplate = async (url: string): Promise<Buffer> => {
  if (FONT_CACHE[url]) {
    return FONT_CACHE[url];
  }
  let fileName = url.substring(url.indexOf('//templates') + '//'.length);
  fileName = fileName.replace(/%20/g, ' ');
  const templatePath = path.join(REPORT_BASE_PATH, 'reports', 'static', fileName);
  if (!existsSync(templatePath)) {
    throw new Error(`unable to find report template ${templatePath}`);
  }
  const data = await fs.readFile(templatePath);
  const result = data;//updateReportTemplate(data, url)
  FONT_CACHE[url] = result;
  return result;
}

const updateReportTemplate = (data: Buffer, url: string): Buffer => {
  const json: Object = JSON.parse(data.toString('utf-8'))
  updateReportItemObject(json, url)
  const result = JSON.stringify(json);
  return Buffer.from(result, 'utf-8')
}
const updateReportItemObject = (item: any, url: string) => {
  if (!item) {
    return;
  }
  if (typeof item === 'object') {
    if (item.Type === 'subreport') {
      const base = url.substr(0, url.lastIndexOf('/') + 1);
      item.ReportName = base + item.ReportName
    }
  }
  const values = Object.values(item)
  for (let value of values) {
    if (Array.isArray(value)) {
      for (let valueItem of value) {
        updateReportItemObject(valueItem, url)
      }
    } else if (typeof value === 'object') {
      updateReportItemObject(value, url)
    }
  }
}